/**
 * Copyright (c) 2013 onionframework.org
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 */
package org.onionframework.faces.component;

import java.io.IOException;
import java.util.Iterator;
import java.util.Map;

import javax.faces.component.EditableValueHolder;
import javax.faces.component.UIComponent;
import javax.faces.component.UINamingContainer;
import javax.faces.component.UISelectBoolean;
import javax.faces.component.UISelectMany;
import javax.faces.component.UISelectOne;
import javax.faces.context.FacesContext;

import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.onionframework.core.exception.SystemException;

/**
 * @author allan
 *
 */
public class UIFragment extends UINamingContainer {

	// ------------------------------------------------------ Manifest Constants

		/**
		 * <p>
		 * The standard component type for this component.
		 * </p>
		 */
		public static final String COMPONENT_TYPE = "org.onionframework.faces.component.Fragment";

		/**
		 * <p>
		 * The standard component family for this component.
		 * </p>
		 */
		public static final String COMPONENT_FAMILY = "javax.faces.NamingContainer";
		
		private boolean disableMenu = true;
		private String[] allowAttributes = new String[] { "readonly", "disabled" };
		private String[] excludes;

		@Override
		public String getFamily() {
			return COMPONENT_FAMILY;
		}

		@Override
		public void encodeBegin(FacesContext context) throws IOException {
			this.disableMenu = !"false".equals(this.getAttributes().get("disableMenu"));
			String excludesValue = (String)this.getAttributes().get("excludes");
			this.excludes = StringUtils.isBlank(excludesValue) ? new String[0] : excludesValue.split("\\,");
			
			Iterator<UIComponent> it = this.getFacetsAndChildren();
			
			UIComponent child;
			while(it.hasNext()){
				child = it.next();
				if(!ArrayUtils.contains(this.excludes, child.getId()))
					this.setAttribute(child, this.getAttributes());
			}
			
			super.encodeBegin(context);
		}

		private void setAttribute(UIComponent component,
				Map<String, Object> attributes) {
			if (component instanceof EditableValueHolder){	
				Object value;
				for (String name : allowAttributes) {			
					value = attributes.get(name);
					
					if(value == null)
						continue;
					
					if (!(value instanceof Boolean))
						value = "true".equals(value);
					
					try {
						
						if("readonly".equals(name) && this.disableMenu && (component instanceof UISelectOne
								|| component instanceof UISelectMany
								|| component instanceof UISelectBoolean))
								name = "disabled";
						
						if(!ArrayUtils.contains(this.excludes, component.getId())){
							component.getAttributes().put(name, value);
						}
					}catch (Exception e) {
						throw new SystemException(e);
					}
				}
			}
			
			Iterator<UIComponent> it = component.getFacetsAndChildren();
			UIComponent child;
			while(it.hasNext()){
				child = it.next();
				if(!ArrayUtils.contains(this.excludes, child.getId()))
					this.setAttribute(child, this.getAttributes());
			}
		}
}
